package com.wispx.gateway.core.filter.gray;

import cn.hutool.json.JSONUtil;
import com.wispx.gateway.config.manager.DynamicConfigManager;
import com.wispx.gateway.config.pojo.RouteDefinition;
import com.wispx.gateway.config.pojo.ServiceInstance;
import com.wispx.gateway.config.util.FilterConfigUtil;
import com.wispx.gateway.core.context.GatewayContext;
import com.wispx.gateway.core.filter.Filter;
import com.wispx.gateway.core.filter.gray.strategy.GrayStrategy;

import java.util.List;
import java.util.Optional;

import static com.wispx.gateway.common.constant.FilterConstant.GRAY_FILTER_NAME;
import static com.wispx.gateway.common.constant.FilterConstant.GRAY_FILTER_ORDER;

public class GrayFilter implements Filter {
    @Override
    public void doPreFilter(GatewayContext ctx) {
        // 获取路由配置
        RouteDefinition.FilterConfig filterConfig = FilterConfigUtil.findFilterConfigByName(ctx.getRouteDefinition().getFilterConfigs(), GRAY_FILTER_NAME);
        filterConfig = Optional.ofNullable(filterConfig).orElse(FilterConfigUtil.buildDefaultGrayFilterConfig());

        if (!filterConfig.isEnable()) {
            ctx.doFilter();
            return;
        }

        List<ServiceInstance> instances = DynamicConfigManager.getInstance()
                .getServiceInstanceByServiceName(ctx.getRequest().getServiceDefinition().getServiceName())
                .values().stream().toList();
        if (instances.stream().anyMatch(instance -> instance.isEnable() && instance.isGray())) {
            GrayStrategy grayStrategy =
                    selectGrayStrategy(JSONUtil.toBean(filterConfig.getConfig(), RouteDefinition.GaryFilterConfig.class));
            ctx.getRequest().setGray(grayStrategy.shouldRoute2Gray(ctx, instances));
        } else {
            // 没有灰度实例，不走灰度
            ctx.getRequest().setGray(false);
        }
        ctx.doFilter();
    }

    @Override
    public void doPostFilter(GatewayContext ctx) {
        ctx.doFilter();
    }

    @Override
    public String mark() {
        return GRAY_FILTER_NAME;
    }

    @Override
    public int getOrder() {
        return GRAY_FILTER_ORDER;
    }

    private GrayStrategy selectGrayStrategy(RouteDefinition.GaryFilterConfig garyFilterConfig) {
        return GrayStrategyManager.getGrayStrategy(garyFilterConfig.getStrategyName());
    }
}
